package com.zjw.protobuf.service;

import com.google.protobuf.Empty;
import com.zjw.protobuf.message.KeyCodeProto;
import com.zjw.protobuf.message.PointProto;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;

import java.awt.*;

@GrpcService
public class MouseServiceImpl extends MouseServiceGrpc.MouseServiceImplBase {

    private volatile Robot robot;

    private GraphicsDevice[] graphicsDevices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();

    public MouseServiceImpl() {
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

    /**
     * 移动鼠标
     *
     * @param responseObserver 响应数据
     */
    @Override
    public StreamObserver<PointProto.Point> moveMouse(StreamObserver<Empty> responseObserver) {
        return new StreamObserver<PointProto.Point>() {

            @Override
            public void onNext(PointProto.Point point) {
                moveMouse(point);
            }

            @Override
            public void onError(Throwable throwable) {
                throwable.printStackTrace();
            }

            @Override
            public void onCompleted() {
                responseObserver.onNext(null);
                responseObserver.onCompleted();
            }
        };
    }

    @Override
    public StreamObserver<KeyCodeProto.KeyCode> keyPress(StreamObserver<Empty> responseObserver) {
        return new StreamObserver<KeyCodeProto.KeyCode>() {

            @Override
            public void onNext(KeyCodeProto.KeyCode keyCode) {
//                keyCode.getType()
            }

            @Override
            public void onError(Throwable throwable) {
                throwable.printStackTrace();
            }

            @Override
            public void onCompleted() {
                responseObserver.onNext(null);
                responseObserver.onCompleted();
            }
        };
    }

    public void moveMouse(PointProto.Point point) {
        robot.mouseWheel((int) point.getY());
        PointerInfo pointerInfo = MouseInfo.getPointerInfo();
        Point mouseLocation = pointerInfo.getLocation();
        int newMouseX = (int) (point.getX() + mouseLocation.getX());
        int newMouseY = (int) (point.getY() + mouseLocation.getY());
        for (GraphicsDevice screenDevice : graphicsDevices) {
            if (inArea(screenDevice.getDefaultConfiguration().getBounds(), newMouseX, newMouseY)) {
                robot.mouseMove(newMouseX, newMouseY);
                return;
            }
        }
        Rectangle rectangle = MouseInfo.getPointerInfo().getDevice().getDefaultConfiguration().getBounds();
        if (newMouseY < rectangle.getY()) {
            newMouseY = (int) rectangle.getY();
        } else if (newMouseY >= rectangle.getY() + rectangle.getHeight()) {
            newMouseY = (int) (rectangle.getY() + rectangle.getHeight() - 1);
        }

        if (newMouseX < rectangle.getX()) {
            newMouseX = (int) rectangle.getX();
        } else if (newMouseX >= rectangle.getX() + rectangle.getWidth()) {
            newMouseX = (int) (rectangle.getX() + rectangle.getWidth() - 1);
        }
        robot.mouseMove(newMouseX, newMouseY);
    }


    public boolean xInArea(Rectangle rectangle, int x) {
        return x >= rectangle.getX() && x < rectangle.getX() + rectangle.getWidth();
    }

    public boolean yInArea(Rectangle rectangle, int y) {
        return y >= rectangle.getY() && y < rectangle.getY() + rectangle.getHeight();
    }

    public boolean inArea(Rectangle rectangle, int x, int y) {
        return xInArea(rectangle, x) && yInArea(rectangle, y);
    }
}
